QuickOPC User's Guide and Reference
Isolated Clients and Subscribers
Fundamentals > Components and Objects > Computational Objects > Isolated Clients and Subscribers

Normally, instances of a client or subscriber object (such as EasyDAClient, EasyAEClient, EasyUAClient) act commonly, sharing the same connections to the target OPC servers (or to the message-oriented middleware, in case of PubSub), and also many common parameters. This way, you can create a large number of these instances and work with them in an easy way, without having to worry about negative effects on the target. If, for example, you create two instances of an EasyDAClient object, and subscribe to some OPC items in each of these instances, only one connection will be created to the OPC server.

This approach works well for most applications, and it allows easy coding in scenarios such as Web development, where each page request may require OPC operations, and the requests may be coming in quick succession and in large numbers, and even processed in parallel.

In some cases, however, you may want to have a dedicated connection to the OPC server, or have more control over the parameters of the connection. In such case, you can set the Isolated property of the EasyXXClient or EasyXXSubscriber object to ‘true’. By doing so, operations invoked on this instance of the client object will work with their own connection to the target OPC server, or message-oriented middleware. We say that the client (subscriber) object is isolated.

If you create more such isolated client objects, each of them will work with its own connection. Obviously you need to be more careful with this approach, in order to keep the load on the target OPC server in reasonable limits.

Examples

// This example shows how to create and use two isolated client objects, resulting in two separate connections to the target
// OPC DA server.

using System;
using System.Diagnostics;
using System.Threading;
using OpcLabs.EasyOpc.DataAccess;
using OpcLabs.EasyOpc.DataAccess.OperationModel;

namespace DocExamples.DataAccess._EasyDAClient
{
    class Isolated
    {
        public static void Main1()
        {
            // Instantiate the client objects and make them isolated
            var client1 = new EasyDAClient { Isolated = true };
            var client2 = new EasyDAClient { Isolated = true };

            // The callback is a local method the displays the value
            void ItemChangedCallback(object sender, EasyDAItemChangedEventArgs eventArgs)
            {
                Debug.Assert(!(eventArgs is null));

                Console.Write($"[{eventArgs.Arguments.State}] ");
                if (eventArgs.Succeeded)
                {
                    Debug.Assert(!(eventArgs.Vtq is null));
                    Console.WriteLine(eventArgs.Vtq.ToString());
                }
                else
                    Console.WriteLine("*** Failure: {0}", eventArgs.ErrorMessageBrief);
            }

            Console.WriteLine("Subscribing...");
            client1.SubscribeItem("", "OPCLabs.KitServer.2", "Simulation.Random", 1000, ItemChangedCallback, state: 1);
            client2.SubscribeItem("", "OPCLabs.KitServer.2", "Simulation.Random", 1000, ItemChangedCallback, state: 2);

            Console.WriteLine("Processing item changed events for 10 seconds...");
            Thread.Sleep(10 * 1000);

            Console.WriteLine("Unsubscribing...");
            client1.UnsubscribeAllItems();
            client2.UnsubscribeAllItems();

            Console.WriteLine("Waiting for 2 seconds...");
            Thread.Sleep(2 * 1000);
        }
    }
}
# This example shows how to create and use two isolated client objects, resulting in two separate connections to the
# target OPC DA server.

# The QuickOPC package is needed. Install it using "pip install opclabs_quickopc".
import opclabs_quickopc
import time

# Import .NET namespaces.
from OpcLabs.EasyOpc.DataAccess import *


# Item changed event handler
def itemChangedCallback(sender, eventArgs):
    assert eventArgs is not None
    print('[', eventArgs.Arguments.State, '] ', sep='', end='')
    if eventArgs.Succeeded:
        assert eventArgs.Vtq is not None
        print(eventArgs.Vtq)
    else:
        print('*** Failure: ', eventArgs.ErrorMessageBrief, sep='')


# Instantiate the client objects and make them isolated.
client1 = EasyDAClient()
client1.Isolated = True
client2 = EasyDAClient()
client2.Isolated = True

print('Subscribing item changes...')
IEasyDAClientExtension.SubscribeItem(client1,
                                     '', 'OPCLabs.KitServer.2', 'Simulation.Random', 1000,
                                     EasyDAItemChangedEventHandler(itemChangedCallback), 1)
IEasyDAClientExtension.SubscribeItem(client2,
                                     '', 'OPCLabs.KitServer.2', 'Simulation.Random', 1000,
                                     EasyDAItemChangedEventHandler(itemChangedCallback), 2)

print('Processing item change notifications for 10 seconds...')
time.sleep(10)

print('Unsubscribing all items...')
client1.UnsubscribeAllItems()
client2.UnsubscribeAllItems()

print('Waiting for 2 seconds...')
time.sleep(2)

print('Finished.')
// This example shows how to create and use two isolated client objects, resulting in two separate connections to the target
// OPC UA server.

using System;
using System.Diagnostics;
using OpcLabs.EasyOpc.UA;
using OpcLabs.EasyOpc.UA.OperationModel;

namespace UADocExamples._EasyUAClient
{
    class Isolated
    {
        public static void Main1()
        {
            UAEndpointDescriptor endpointDescriptor =
                "opc.tcp://opcua.demo-this.com:51210/UA/SampleServer";
            // or "http://opcua.demo-this.com:51211/UA/SampleServer" (currently not supported)
            // or "https://opcua.demo-this.com:51212/UA/SampleServer/"

            // Instantiate the client objects and make them isolated
            var client1 = new EasyUAClient { Isolated = true };
            var client2 = new EasyUAClient { Isolated = true };

            // The callback is a local method the displays the value
            void DataChangeCallback(object sender, EasyUADataChangeNotificationEventArgs eventArgs)
            {
                Debug.Assert(!(eventArgs is null));

                Console.Write($"[{eventArgs.Arguments.State}] ");
                if (eventArgs.Succeeded)
                {
                    Debug.Assert(!(eventArgs.AttributeData is null));
                    Console.WriteLine(eventArgs.AttributeData.ToString());
                }
                else
                    Console.WriteLine("*** Failure: {0}", eventArgs.ErrorMessageBrief);
            }

            Console.WriteLine("Subscribing...");
            client1.SubscribeDataChange(endpointDescriptor, "nsu=http://test.org/UA/Data/ ;i=10853", 1000, 
                DataChangeCallback, state: 1);
            client2.SubscribeDataChange(endpointDescriptor, "nsu=http://test.org/UA/Data/ ;i=10853", 1000,
                DataChangeCallback, state: 2);

            Console.WriteLine("Processing data change events for 10 seconds...");
            System.Threading.Thread.Sleep(10 * 1000);

            Console.WriteLine("Unsubscribing...");
            client1.UnsubscribeAllMonitoredItems();
            client2.UnsubscribeAllMonitoredItems();

            Console.WriteLine("Waiting for 2 seconds...");
            System.Threading.Thread.Sleep(2 * 1000);
        }
    }
}
# This example shows how to create and use two isolated client objects, resulting in two separate connections to the
# target OPC UA server.

# The QuickOPC package is needed. Install it using "pip install opclabs_quickopc".
import opclabs_quickopc
import time

# Import .NET namespaces.
from OpcLabs.EasyOpc.UA import *
from OpcLabs.EasyOpc.UA.OperationModel import *


# The callback is a regular method the displays the value.
def dataChangeCallback(sender, eventArgs):
    print('[', eventArgs.Arguments.State, '] ', sep='', end='')
    if eventArgs.Succeeded:
        assert eventArgs.AttributeData is not None
        print('Value: ', eventArgs.AttributeData.Value, sep='')
    else:
        print('*** Failure: ', eventArgs.ErrorMessageBrief, sep='')


endpointDescriptor = UAEndpointDescriptor('opc.tcp://opcua.demo-this.com:51210/UA/SampleServer')
# or 'http://opcua.demo-this.com:51211/UA/SampleServer' (currently not supported)
# or 'https://opcua.demo-this.com:51212/UA/SampleServer/'

# Instantiate the client objects and make them isolated.
client1 = EasyUAClient()
client1.Isolated = True
client2 = EasyUAClient()
client2.Isolated = True

print('Subscribing...')
IEasyUAClientExtension.SubscribeDataChange(client1,
    endpointDescriptor,
    UANodeDescriptor('nsu=http://test.org/UA/Data/ ;i=10853'),
    1000,
    EasyUADataChangeNotificationEventHandler(dataChangeCallback),
    1)  # state
IEasyUAClientExtension.SubscribeDataChange(client2,
    endpointDescriptor,
    UANodeDescriptor('nsu=http://test.org/UA/Data/ ;i=10853'),
    1000,
    EasyUADataChangeNotificationEventHandler(dataChangeCallback),
    2)  # state

print('Processing data change events for 10 seconds...')
time.sleep(10)

print('Unsubscribing...')
client1.UnsubscribeAllMonitoredItems()
client2.UnsubscribeAllMonitoredItems()

print('Waiting for 2 seconds...')
time.sleep(2)

print('Finished.')

 

See Also

Examples - OPC Data Access

Examples - OPC Unified Architecture